package cn.itcast.protocol;

import cn.itcast.message.LoginRequestMessage;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.logging.LoggingHandler;

/**
 * 测试MessageCodec
 */
public class TestMessageCodec {
    public static void main(String[] args) throws Exception {

        //打印日志用的 我们可以根据日志信息数一下魔数还有其他的信息 然后再数一数内容数量 会发现都是对的
        //因为这个handler的作用主要是打印日志信息而已 而且点进去会发现是被标注有@Sharable注解的 这注解表明netty从分考虑过 这个handler是可以再并发环境下共享的
        //因为是可以再并发环境下共享的所以我们可以抽取出来 给多个channel去共享这一个对象即可，就不用每次一个channel都要单独建一个处理器
        //真正干活的是eventLoop对象他是一个线程对应一个的 然后这些处理器可以每个工人分配一个也可以所有工人一起用一个(并发线程安全问题)
        //所以打印日志的这种处理器肯定是可以抽取为共用的 但是具体处理数据读取的这种就得区分开了不然很容易跟其他线程的数据混在一起(并发问题)
        LoggingHandler LOGGING_HANDLER =  new LoggingHandler();

        EmbeddedChannel channel = new EmbeddedChannel(
                //处理半包闭包问题的处理器
                //最大数据长度不超过1024个字节 长度标识 前有12个字节的其他标识字段 有4个字节表示长度 所以总共就是16个标识符
                //根据我们自己的规则可以看出我们内容前总共有16个字节 其中4个字节是表示长度的 所以我们定义好这个来规范 数据格式跟长度就可以解决下面说的半包问题
                //后面2个0表示 长度不需要位移 消息需要去除哪些补份 我们不需要位移 而且消息 因为我们encode /decode中不是还得自己解析嘛 所以肯定不能去除
                //当接收到的数据少于规定的后(比如标识缺少或者规定内容是100但是只接收到了50) 这个处理器就会一直等待继续接收数据 直到接收到那么多少数据为止才会往下执行 就会避免报错
                //所以这种情况下肯定就有多线程的数据共享问题 如果共享使用的话 首先最大长度1024字节都被共享使用了 那还搞毛
                //所以这个处理器就肯定只能一个eventLoop自己一个不能共享  点进去也会发现并没有标注@Sharable注解
                new LengthFieldBasedFrameDecoder(1024,12,4,0,0),
                LOGGING_HANDLER,
                new MessageCodec());

        LoginRequestMessage message = new LoginRequestMessage("zhangsan","123" );

        //那么当我们这个message信息写出去的时候就会经过出站处理器  即MessageCodec的encode()
        //java对象转换成二进制数据 这个二进制数据就是具体的内容
        channel.writeOutbound(message);

        //入站测试方法 测试MessageCodec类中的decode方法
        //我们得自己弄一个编码好的数据才能拿来解码太麻烦了 所以我们可以再调用一次encode 然后用这个encode的数据来测试解码
        ByteBuf buf = ByteBufAllocator.DEFAULT.buffer();
        new MessageCodec().encode(null,message,buf ); //这样message就会被编码好然后存到buf中


        //目前的这个编解码器MessageCodec是没有闭包问题的数据可以多, 但是数据不可以少，因为少可能版本号或者序列号等的数据都没有
        //那么处理肯定就会报错最起码都回空指针问题 我们可以用我们以前学的LengthFieldBasedFrameDecoder处理器来处理
        //加了这个处理器后 如果长度字节不够 他就会一直等待 直到接收到那么多的信息才行, 没收到前会一直等这样就避免了报错

        //入站
        channel.writeInbound(buf);


    }
}
